package org.example;

import java.sql.*;
import java.util.Base64;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

public class AccountService {// 账户业务逻辑类
    private final Connection connection;// 数据库连接

    public AccountService(Connection connection) {// 构造函数，接收数据库连接
        this.connection = connection;
    }

    //用户登录验证
    public Account login(String accountId, String password) throws SQLException {// 登录验证
        String sql = "SELECT * FROM yt_account WHERE account_id = ? AND password = ?";// 查询账户信息
        try (PreparedStatement pstmt = connection.prepareStatement(sql)) {// 查询账户信息
            pstmt.setString(1, accountId);// 设置账户ID
            pstmt.setString(2, encryptPassword(password));// 设置密码
            try (ResultSet rs = pstmt.executeQuery()) {// 查询账户信息
                if (rs.next()) {// 如果有记录
                    Account account = new Account();// 创建账户对象
                    account.setAccountId(rs.getString("account_id"));// 设置账户ID
                    account.setName(rs.getString("name"));// 设置姓名
                    account.setPassword(rs.getString("password"));// 设置密码
                    account.setBalance(rs.getDouble("balance"));// 设置余额
                    return account;// 返回账户对象
                }
            }
        }
        return null;// 登录失败
    }

    /**
     * 修改密码
     * @param accountId 账户号码
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     * @return 修改成功返回true，失败返回false
     * @throws SQLException 数据库异常
     */
    public boolean changePassword(String accountId, String oldPassword, String newPassword)
            throws SQLException {
        // 验证旧密码
        String verifySql = "SELECT 1 FROM yt_account WHERE account_id = ? AND password = ?";
        PreparedStatement verifyStmt = null;
        ResultSet rs = null;
        try {
            verifyStmt = connection.prepareStatement(verifySql);// 验证旧密码
            verifyStmt.setString(1, accountId);// 设置账户ID
            verifyStmt.setString(2, encryptPassword(oldPassword));// 设置密码
            rs = verifyStmt.executeQuery();// 执行查询
            if (!rs.next()) {// 如果没有记录
                LoggerUtil.logOperation(accountId, "密码修改失败：旧密码错误");// 记录日志
                return false;// 修改失败
            }
        } finally {// 关闭资源
            DatabaseUtil.close(rs);// 关闭结果集
            DatabaseUtil.close(verifyStmt);// 关闭语句
        }

        // 更新密码
        String updateSql = "UPDATE yt_account SET password = ? WHERE account_id = ?";// 更新密码
        PreparedStatement updateStmt = null;// 声明语句对象
        try {
            updateStmt = connection.prepareStatement(updateSql);// 准备语句
            updateStmt.setString(1, encryptPassword(newPassword));// 设置密码
            updateStmt.setString(2, accountId);// 设置账户ID
            int rows = updateStmt.executeUpdate();// 执行更新
            if (rows > 0) {// 如果更新成功
                LoggerUtil.logOperation(accountId, "密码修改成功");// 记录日志
                return true;// 修改成功
            }
            return false;// 修改失败
        } catch (SQLException e) {// 捕获异常
            LoggerUtil.logError("修改密码异常", e);// 记录日志
            throw e;// 抛出异常
        } finally {
            DatabaseUtil.close(updateStmt);// 关闭语句
        }
    }
    /**
     * 存款操作
     * @param accountId 账户号码
     * @param amount 存款金额
     * @throws SQLException 数据库异常
     */
    public void deposit(String accountId, double amount) throws SQLException {// 存款操作
        String sql = "UPDATE yt_account SET balance = balance + ? WHERE account_id = ?";// 更新余额
        PreparedStatement stmt = null;// 声明语句对象
        try {// 捕获异常
            stmt = connection.prepareStatement(sql);// 准备语句
            stmt.setDouble(1, amount);// 设置金额
            stmt.setString(2, accountId);// 设置账户ID
            stmt.executeUpdate();// 执行更新
            LoggerUtil.logOperation(accountId, String.format("存款 %.2f 元", amount));// 记录日志
        } catch (SQLException e) {// 捕获异常
            LoggerUtil.logError("存款操作异常", e);// 记录日志
            throw e;// 抛出异常
        } finally {// 关闭资源
            DatabaseUtil.close(stmt);// 关闭语句
        }
    }
    /**
     * 取款操作
     * @param accountId 账户号码
     * @param amount 取款金额
     * @throws SQLException 数据库异常
     */
    public void withdraw(String accountId, double amount) throws SQLException {
        // 定义SQL语句
        String sql = "UPDATE yt_account SET balance = balance - ? WHERE account_id = ?";
        // 定义PreparedStatement对象
        PreparedStatement stmt = null;

        try {
            // 创建PreparedStatement对象
            stmt = connection.prepareStatement(sql);
            // 设置参数
            stmt.setDouble(1, amount);
            stmt.setString(2, accountId);
            // 执行更新操作
            stmt.executeUpdate();

            // 记录操作日志
            LoggerUtil.logOperation(accountId, String.format("取款 %.2f 元", amount));
        } catch (SQLException e) {
            // 记录错误日志
            LoggerUtil.logError("取款操作异常", e);
            // 抛出异常
            throw e;
        } finally {
            // 关闭PreparedStatement对象
            DatabaseUtil.close(stmt);
        }
    }

    /**
     * 转账操作（使用事务保证数据一致性）
     * @param fromAccountId 转出账户
     * @param toAccountId 转入账户
     * @param amount 转账金额
     * @throws SQLException 数据库异常
     */
    public void transfer(String fromAccountId, String toAccountId, double amount, TransactionService transactionService)
            throws SQLException {
        try {
            connection.setAutoCommit(false); // 开始事务

            LoggerUtil.logOperation(fromAccountId,
                    String.format("开始转账 %.2f 元到 %s", amount, toAccountId));// 记录日志

            // 检查转出账户余额
            String checkSql = "SELECT balance FROM yt_account WHERE account_id = ? FOR UPDATE";// 查询余额
            PreparedStatement checkStmt = connection.prepareStatement(checkSql);// 准备语句
            checkStmt.setString(1, fromAccountId);// 设置账户ID
            ResultSet checkRs = checkStmt.executeQuery();// 执行查询
            if (!checkRs.next()) {// 如果没有记录
                throw new SQLException("转出账户不存在");// 抛出异常
            }
            double fromBalance = checkRs.getDouble("balance");// 获取余额
            if (fromBalance < amount) {// 如果余额不足
                throw new SQLException("余额不足");// 抛出异常
            }
            // 从转出账户扣款
            withdraw(fromAccountId, amount);// 取款
            // 向转入账户存款
            deposit(toAccountId, amount);// 存款
            // 获取转账后的余额
            String balanceSql = "SELECT balance FROM yt_account WHERE account_id = ?";
            PreparedStatement balanceStmt = connection.prepareStatement(balanceSql);// 准备语句
            // 转出账户余额
            balanceStmt.setString(1, fromAccountId);// 设置账户ID
            ResultSet fromRs = balanceStmt.executeQuery();// 执行查询
            fromRs.next();// 移动到第一条记录
            double fromBalanceAfter = fromRs.getDouble("balance");// 获取余额
            // 转入账户余额
            balanceStmt.setString(1, toAccountId);// 设置账户ID
            ResultSet toRs = balanceStmt.executeQuery();// 执行查询
            toRs.next();// 移动到第一条记录
            double toBalanceAfter = toRs.getDouble("balance");// 获取余额
            // 记录两条交易流水
            // 转出记录（转出账户视角）
            transactionService.recordTransaction(// 记录交易流水
                    fromAccountId,
                    "转出",
                    amount,
                    toAccountId,
                    fromBalanceAfter
            );
            // 转入记录（转入账户视角）
            transactionService.recordTransaction(// 记录交易流水
                    toAccountId,
                    "转入",
                    amount,
                    fromAccountId,
                    toBalanceAfter
            );
            connection.commit(); // 提交事务
            LoggerUtil.logOperation(fromAccountId,// 记录日志
                    String.format("成功转账 %.2f 元到 %s", amount, toAccountId));// 记录日志
        } catch (SQLException e) {// 捕获异常
            connection.rollback(); // 回滚事务
            LoggerUtil.logOperation(fromAccountId,// 记录日志
                    String.format("转账失败: %s", e.getMessage()));// 记录日志
            LoggerUtil.logError("转账操作异常", e);// 记录日志
            throw e;// 抛出异常
        } finally {
            connection.setAutoCommit(true); // 恢复自动提交模式
        }
    }
    /**
     * 检查账户是否存在
     * @param accountId 账户号码
     * @return 存在返回true，不存在返回false
     * @throws SQLException 数据库异常
     */
    public boolean accountExists(String accountId) throws SQLException {
        // 定义SQL语句
        String sql = "SELECT 1 FROM yt_account WHERE account_id = ?";
        // 声明PreparedStatement对象
        PreparedStatement stmt = null;
        // 声明ResultSet对象
        ResultSet rs = null;

        try {
            // 创建PreparedStatement对象
            stmt = connection.prepareStatement(sql);
            // 设置参数
            stmt.setString(1, accountId);
            // 执行查询
            rs = stmt.executeQuery();
            // 返回查询结果
            return rs.next();
        } finally {
            // 关闭ResultSet对象
            DatabaseUtil.close(rs);
            // 关闭PreparedStatement对象
            DatabaseUtil.close(stmt);
        }
    }

    /**
     * 获取账户余额
     * @param accountId 账户号码
     * @return 账户余额
     * @throws SQLException 数据库异常
     */
    public double getAccountBalance(String accountId) throws SQLException {
        // 定义SQL语句
        String sql = "SELECT balance FROM yt_account WHERE account_id = ?";
        // 定义PreparedStatement对象
        PreparedStatement stmt = null;
        // 定义ResultSet对象
        ResultSet rs = null;

        try {
            // 创建PreparedStatement对象
            stmt = connection.prepareStatement(sql);
            // 设置参数
            stmt.setString(1, accountId);
            // 执行查询
            rs = stmt.executeQuery();

            // 判断查询结果是否为空
            if (rs.next()) {
                // 返回账户余额
                return rs.getDouble("balance");
            }
            // 抛出异常，账户不存在
            throw new SQLException("账户不存在");
        } finally {
            // 关闭ResultSet对象
            DatabaseUtil.close(rs);
            // 关闭PreparedStatement对象
            DatabaseUtil.close(stmt);
        }
    }

    /**
     * 简单的密码加密方法（
     */
    private String encryptPassword(String password) {
        // 简单 Base64 编码
        return Base64.getEncoder().encodeToString(password.getBytes());
    }
}